package com.ruoyi.system.service.impl;

import java.io.*;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import com.ruoyi.system.domain.ModuleVolumeInfo;
import com.ruoyi.system.domain.comment.FileComment;
import com.ruoyi.system.mapper.ModuleVolumeInfoMapper;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.ModuleFileInfoMapper;
import com.ruoyi.system.domain.ModuleFileInfo;
import com.ruoyi.system.service.IModuleFileInfoService;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;

import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

import javax.imageio.IIOImage;

import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.FileImageOutputStream;
import javax.imageio.stream.ImageOutputStream;



/**
 * 文件信息Service业务层处理
 *
 * @author ruoyi
 * @date 2023-07-12
 */
@Service
public class ModuleFileInfoServiceImpl implements IModuleFileInfoService
{
    @Autowired
    private ModuleFileInfoMapper moduleFileInfoMapper;

    @Autowired
    private ModuleVolumeInfoMapper moduleVolumeInfoMapper;

    /**
     * 查询文件信息
     *
     * @param id 文件信息主键
     * @return 文件信息
     */
    @Override
    public ModuleFileInfo selectModuleFileInfoById(String id)
    {
        return moduleFileInfoMapper.selectModuleFileInfoById(id);

    }

    /**
     * 查询文件注释信息列表
     *
     * @return 文件信息集合
     */
    public List<FileComment> selectModuleFileComInfoList(){
        return moduleFileInfoMapper.selectModuleFileComInfoList();
    }



    /**
     *
     * 批量下载
     *
     */
    public ResponseEntity<byte[]> downloadMore(String[] ids){
        String filePath = "D:\\temporaryFolder";
        String zipPath = "D:\\fileZip.zip";
        try{
            File folder = new File(filePath);
            if(!folder.exists()){
                folder.mkdirs();
            }

            for(String fileId : ids){
                String id = fileId.replace("++","/");
                moveToFolder(id);
            }
            zipFolder(filePath,zipPath);
            byte[] zipFileData = readZipFile(zipPath);

            File folderToDelete = new File(filePath);
            deleteFolderAndContents(folderToDelete);
            File zipFileToDelete = new File(zipPath);
            deleteFile(zipFileToDelete);
            return ResponseEntity.ok().header("Content-Type","application/zip").body(zipFileData);
        }catch (IOException e){
            e.printStackTrace();
            return ResponseEntity.badRequest().build();
        }
    }

    public void moveToFolder(String id) throws IOException {
        ModuleFileInfo moduleFileInfo = moduleFileInfoMapper.selectModuleFileInfoById(id);
        if(moduleFileInfo.getFileReserved4() != null && moduleFileInfo.getFileReserved4() == 1L){
            String temp = "D:" + moduleFileInfo.getFilepath() + moduleFileInfo.getId() + "."+ moduleFileInfo.getFiletype().toLowerCase();
            File oldFile = new File(temp);
            String targetPath = "D:\\temporaryFolder\\" + moduleFileInfo.getFilename();
            File newFile = new File(targetPath);
            Files.copy(oldFile.toPath(),newFile.toPath());
        }else if(moduleFileInfo.getFileReserved4() != null && moduleFileInfo.getFileReserved4() == 2L){
            String path = "D:" + moduleFileInfo.getFilepath();
            String tempPath = "D:\\temporaryFileFolder\\" + toLowerCaseExtension(moduleFileInfo.getFilename());
            mergeTiff(path, tempPath);
            File oldFile = new File(tempPath);
            String targetPath = "D:\\temporaryFolder\\" + toLowerCaseExtension(moduleFileInfo.getFilename());
            File newFile = new File(targetPath);
            Files.copy(oldFile.toPath(),newFile.toPath());
            deleteFile(oldFile);
        }else{
            ModuleVolumeInfo moduleVolumeInfo = moduleVolumeInfoMapper.selectModuleVolumeInfoById(moduleFileInfo.getVolumeid());
            String folderPath = moduleVolumeInfo.getPath() + File.separator;
            String houzhui = "pdf";
            File VolumeFolder = new File(folderPath);
            if(VolumeFolder.isDirectory()){
                Map<String,String> fileDetails = new HashMap<>();
                readFiles(VolumeFolder,fileDetails);
                houzhui = fileDetails.get(moduleFileInfo.getFilename());
            }
            File oldFile = new File(moduleVolumeInfo.getPath() + File.separator + moduleFileInfo.getFilename() + "." + houzhui);
            String targetPath = "D:\\temporaryFolder\\" + moduleFileInfo.getFilename() + "." + houzhui;
            File newFile = new File(targetPath);
            Files.copy(oldFile.toPath(),newFile.toPath());
        }
    }

    public void zipFolder(String folderPath, String zipFileName) throws IOException {
        File folder = new File(folderPath);

        if (folder.exists() && folder.isDirectory()) {
            try (FileOutputStream fos = new FileOutputStream(zipFileName);
                 ZipOutputStream zos = new ZipOutputStream(fos)) {
                for (File file : folder.listFiles()) {
                    if (file.isFile()) {
                        ZipEntry zipEntry = new ZipEntry(file.getName());
                        zos.putNextEntry(zipEntry);

                        try (FileInputStream fis = new FileInputStream(file)) {
                            byte[] buffer = new byte[1024];
                            int length;
                            while ((length = fis.read(buffer)) > 0) {
                                zos.write(buffer, 0, length);
                            }
                        }

                        zos.closeEntry();
                    }
                }
            }
        }
    }

    private byte[] readZipFile(String zipFileName) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        FileInputStream fis = new FileInputStream(zipFileName);
        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = fis.read(buffer)) != -1) {
            baos.write(buffer, 0, bytesRead);
        }
        fis.close();
        return baos.toByteArray();
    }

    private static boolean deleteFolderAndContents(File folder) {
        if (folder.exists()) {
            File[] files = folder.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        if (!deleteFolderAndContents(file)) {
                            return false;
                        }
                    } else {
                        if (!deleteFile(file)) {
                            return false;
                        }
                    }
                }
            }
            return folder.delete();
        }
        return false;
    }

    private static boolean deleteFile(File file) {
        if (file.exists()) {
            return file.delete();
        }
        return false;
    }

    public static String toLowerCaseExtension(String fileName) {
        int lastDotIndex = fileName.lastIndexOf('.');
        if (lastDotIndex > 0) { // 确保至少有一个点，并且它不是第一个字符
            String namePart = fileName.substring(0, lastDotIndex);
            String extensionPart = fileName.substring(lastDotIndex + 1).toLowerCase();
            return namePart + "." + extensionPart;
        }
        return fileName; // 如果没有找到点，则返回原字符串
    }

    /**
     * 获取二进制文件
     *
     * @param id 文件信息主键
     * @return pdf
     */
    public ResponseEntity<byte[]> getpdf(String id){
        try {
            ModuleFileInfo moduleFileInfo = moduleFileInfoMapper.selectModuleFileInfoById(id);
            if(moduleFileInfo.getFileReserved4() != null && moduleFileInfo.getFileReserved4() == 1L){
                String path = "D:" + moduleFileInfo.getFilepath() + moduleFileInfo.getId() + "."+ moduleFileInfo.getFiletype().toLowerCase();
                File localFile = new File(path);

                // 将PDF文件内容转换为字节数组
                byte[] localBytes = Files.readAllBytes(localFile.toPath());
                return ResponseEntity.ok().header("Content-Type", "application/pdf").body(localBytes);
            }else if(moduleFileInfo.getFileReserved4() != null && moduleFileInfo.getFileReserved4() == 2L){
                return mergeTiff(id);
            }
            // 从classpath中加载PDF文件
            ModuleVolumeInfo moduleVolumeInfo = moduleVolumeInfoMapper.selectModuleVolumeInfoById(moduleFileInfo.getVolumeid());
            String folderPath = moduleVolumeInfo.getPath() + File.separator;
            String houzhui = "pdf";
            File folder = new File(folderPath);
            if(folder.isDirectory()){
                Map<String,String> fileDetails = new HashMap<>();
                readFiles(folder,fileDetails);
                houzhui = fileDetails.get(moduleFileInfo.getFilename());
            }
            File localFile = new File(moduleVolumeInfo.getPath() + File.separator + moduleFileInfo.getFilename() + "." + houzhui);

            // 将PDF文件内容转换为字节数组
            byte[] localBytes = Files.readAllBytes(localFile.toPath());
            return ResponseEntity.ok().header("Content-Type", "application/pdf").body(localBytes);
        }catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.badRequest().build();
        }
    }

    //读取文件名称与类型
    public static void readFiles(File folder, Map<String, String> fileDetails) {
        File[] files = folder.listFiles(); // 获取文件夹中的所有文件
        for (File file : files) {
            if (file.isDirectory()) {
                readFiles(file, fileDetails); // 递归遍历子文件夹中的文件
            } else {
                String fileName = file.getName();
                String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
                String nameWithoutExtension = fileName.substring(0, fileName.lastIndexOf("."));
                fileDetails.put(nameWithoutExtension, fileType); // 将不带类型的文件名称和类型存储到字典中
            }
        }
    }

    /**
     * 获取Type
     *
     * @param id 文件信息主键
     * @return type
     */
    public String getType(String id){
        ModuleFileInfo moduleFileInfo = moduleFileInfoMapper.selectModuleFileInfoById(id);
        if(moduleFileInfo.getFileReserved4() != null && moduleFileInfo.getFileReserved4() == 1L){
            if(moduleFileInfo.getFiletype().equalsIgnoreCase("tif")) return "tiff";
            else return moduleFileInfo.getFiletype();
        }else if(moduleFileInfo.getFileReserved4() != null && moduleFileInfo.getFileReserved4() == 2L){
            return "tiff";
        }
        ModuleVolumeInfo moduleVolumeInfo = moduleVolumeInfoMapper.selectModuleVolumeInfoById(moduleFileInfo.getVolumeid());
        String folderPath = moduleVolumeInfo.getPath() + File.separator;
        String houzhui = "pdf";
        File folder = new File(folderPath);
        if(folder.isDirectory()){
            Map<String,String> fileDetails = new HashMap<>();
            readFiles(folder,fileDetails);
            houzhui = fileDetails.get(moduleFileInfo.getFilename());
        }
        return houzhui;
    }

    public ResponseEntity<byte[]> mergePdf(String id) {
        try {
            ModuleFileInfo moduleFileInfo = moduleFileInfoMapper.selectModuleFileInfoById(id);
            String path =  "D:" + moduleFileInfo.getFilepath();
            String tempPath = "D:\\temporaryFileFolder\\file.pdf";
            convertTifToPdf(path, tempPath);
            File localFile = new File(tempPath);
            byte[] localBytes = Files.readAllBytes(localFile.toPath());
            return ResponseEntity.ok().header("Content-Type", "application/pdf").body(localBytes);

        }catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.badRequest().build();
        }
    }

    public ResponseEntity<byte[]> mergeTiff(String id) {
        try {
            ModuleFileInfo moduleFileInfo = moduleFileInfoMapper.selectModuleFileInfoById(id);
            String path = "D:" + moduleFileInfo.getFilepath();
            String tempPath = "D:\\temporaryFileFolder\\file.tiff";
            mergeTiff(path, tempPath);
            File localFile = new File(tempPath);
            byte[] localBytes = Files.readAllBytes(localFile.toPath());
            deleteFile(localFile);
            return ResponseEntity.ok().header("Content-Type", "application/pdf").body(localBytes);

        }catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.badRequest().build();
        }
    }

    public static void mergeTiff(String folderPath, String outputPath) {
        try {
            File folder = new File(folderPath);
            File[] files = folder.listFiles((dir, name) -> name.toLowerCase().endsWith(".tif"));
            if (files != null && files.length > 0) {
                // 读取第一个TIF文件以获取图像大小和类型
                BufferedImage firstImage = ImageIO.read(files[0]);
                int width = firstImage.getWidth();
                int height = firstImage.getHeight();
                int type = firstImage.getType();

                // 创建TIFF输出流
                ImageWriter writer = ImageIO.getImageWritersByFormatName("TIFF").next();
                ImageWriteParam param = writer.getDefaultWriteParam();
                param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
                param.setCompressionType("CCITT T.6");
                ImageOutputStream outputStream = new FileImageOutputStream(new File(outputPath));
                writer.setOutput(outputStream);
                writer.prepareWriteSequence(null);

                // 逐个写入TIF文件内容到TIFF文件中
                for (File file : files) {
                    BufferedImage image = ImageIO.read(file);
                    if (image.getWidth() != width || image.getHeight() != height || image.getType() != type) {
                        throw new IllegalArgumentException("All TIFF images must have the same dimensions and type.");
                    }
                    IIOImage iioImage = new IIOImage(image, null, null);
                    writer.writeToSequence(iioImage, param);
                }

                // 结束写入
                writer.endWriteSequence();
                outputStream.close();
                writer.dispose();

                System.out.println("TIFF file created successfully.");
            } else {
                System.out.println("No TIF files found in the folder.");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void convertTifToPdf(String folderPath, String outputPath) {
        try {
            PDDocument document = new PDDocument();
            File folder = new File(folderPath);
            File[] files = folder.listFiles((dir, name) -> name.toLowerCase().endsWith(".tif"));
            if (files != null) {
                for (File file : files) {
                    BufferedImage image = ImageIO.read(file);
                    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                    ImageIO.write(image, "tif", byteArrayOutputStream);
                    PDImageXObject pdImage = PDImageXObject.createFromByteArray(document, byteArrayOutputStream.toByteArray(), "tif");
                    PDPage page = new PDPage();
                    document.addPage(page);
                    try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
                        contentStream.drawImage(pdImage, 0, 0);
                    }
                }
            }
            document.save(outputPath);
            document.close();
            System.out.println("PDF created successfully.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 查询文件信息列表
     *
     * @param moduleFileInfo 文件信息
     * @return 文件信息
     */
    @Override
    public List<ModuleFileInfo> selectModuleFileInfoList(ModuleFileInfo moduleFileInfo)
    {
        return moduleFileInfoMapper.selectModuleFileInfoList(moduleFileInfo);
    }

    /**
     * 新增文件信息
     *
     * @param moduleFileInfo 文件信息
     * @return 结果
     */
    @Override
    public int insertModuleFileInfo(ModuleFileInfo moduleFileInfo)
    {
        return moduleFileInfoMapper.insertModuleFileInfo(moduleFileInfo);
    }

    /**
     * 修改文件信息
     *
     * @param moduleFileInfo 文件信息
     * @return 结果
     */
    @Override
    public int updateModuleFileInfo(ModuleFileInfo moduleFileInfo)
    {
        return moduleFileInfoMapper.updateModuleFileInfo(moduleFileInfo);
    }

    /**
     * 批量删除文件信息
     *
     * @param ids 需要删除的文件信息主键
     * @return 结果
     */
    @Override
    public int deleteModuleFileInfoByIds(String[] ids)
    {
        return moduleFileInfoMapper.deleteModuleFileInfoByIds(ids);
    }

    /**
     * 删除文件信息信息
     *
     * @param id 文件信息主键
     * @return 结果
     */
    @Override
    public int deleteModuleFileInfoById(String id)
    {
        return moduleFileInfoMapper.deleteModuleFileInfoById(id);
    }
}
